home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Misc Servers / Zope.exe / EXTENSIONS.PY < prev    next >
Encoding:
Python Source  |  2000-07-05  |  8.9 KB  |  247 lines

  1. ##############################################################################
  2. # Zope Public License (ZPL) Version 1.0
  3. # -------------------------------------
  4. # Copyright (c) Digital Creations.  All rights reserved.
  5. # This license has been certified as Open Source(tm).
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are
  8. # met:
  9. # 1. Redistributions in source code must retain the above copyright
  10. #    notice, this list of conditions, and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. #    notice, this list of conditions, and the following disclaimer in
  13. #    the documentation and/or other materials provided with the
  14. #    distribution.
  15. # 3. Digital Creations requests that attribution be given to Zope
  16. #    in any manner possible. Zope includes a "Powered by Zope"
  17. #    button that is installed by default. While it is not a license
  18. #    violation to remove this button, it is requested that the
  19. #    attribution remain. A significant investment has been put
  20. #    into Zope, and this effort will continue if the Zope community
  21. #    continues to grow. This is one way to assure that growth.
  22. # 4. All advertising materials and documentation mentioning
  23. #    features derived from or use of this software must display
  24. #    the following acknowledgement:
  25. #      "This product includes software developed by Digital Creations
  26. #      for use in the Z Object Publishing Environment
  27. #      (http://www.zope.org/)."
  28. #    In the event that the product being advertised includes an
  29. #    intact Zope distribution (with copyright and license included)
  30. #    then this clause is waived.
  31. # 5. Names associated with Zope or Digital Creations must not be used to
  32. #    endorse or promote products derived from this software without
  33. #    prior written permission from Digital Creations.
  34. # 6. Modified redistributions of any form whatsoever must retain
  35. #    the following acknowledgment:
  36. #      "This product includes software developed by Digital Creations
  37. #      for use in the Z Object Publishing Environment
  38. #      (http://www.zope.org/)."
  39. #    Intact (re-)distributions of any official Zope release do not
  40. #    require an external acknowledgement.
  41. # 7. Modifications are encouraged but must be packaged separately as
  42. #    patches to official Zope releases.  Distributions that do not
  43. #    clearly separate the patches from the original work must be clearly
  44. #    labeled as unofficial distributions.  Modifications which do not
  45. #    carry the name Zope may be packaged in any form, as long as they
  46. #    conform to all of the clauses above.
  47. # Disclaimer
  48. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  49. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  52. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  55. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  56. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  57. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  58. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. #   SUCH DAMAGE.
  60. # This software consists of contributions made by Digital Creations and
  61. # many individuals on behalf of Digital Creations.  Specific
  62. # attributions are listed in the accompanying credits file.
  63. ##############################################################################
  64. __doc__='''Standard routines for handling extensions.
  65.  
  66. Extensions currently include external methods and pluggable brains.
  67.  
  68. $Id: Extensions.py,v 1.12.36.2 2000/07/05 21:20:41 brian Exp $'''
  69. __version__='$Revision: 1.12.36.2 $'[11:-2]
  70.  
  71. from string import find, split
  72. import os, zlib, rotor, imp
  73. import Products
  74. path_split=os.path.split
  75. path_join=os.path.join
  76. exists=os.path.exists
  77.     
  78. class FuncCode:
  79.  
  80.     def __init__(self, f, im=0):
  81.         self.co_varnames=f.func_code.co_varnames[im:]
  82.         self.co_argcount=f.func_code.co_argcount-im
  83.  
  84.     def __cmp__(self,other):
  85.         if other is None: return 1
  86.         try: return cmp((self.co_argcount, self.co_varnames),
  87.                         (other.co_argcount, other.co_varnames))
  88.         except: return 1
  89.  
  90.  
  91. def _getPath(home, prefix, name, suffixes):
  92.     d=path_join(home, prefix)
  93.     if d==prefix: raise ValueError, (
  94.         'The prefix, %s, should be a relative path' % prefix)
  95.     d=path_join(d,name)
  96.     if d==name: raise ValueError, ( # Paranoia
  97.         'The file name, %s, should be a simple file name' % name)
  98.     for s in suffixes:
  99.         if s: s="%s.%s" % (d, s)
  100.         else: s=d
  101.         if exists(s): return s
  102.  
  103. def getPath(prefix, name, checkProduct=1, suffixes=('',)):
  104.     """Find a file in one of several relative locations
  105.  
  106.     Arguments:
  107.  
  108.       prefix -- The location, relative to some home, to look for the
  109.                 file
  110.  
  111.       name -- The name of the file.  This must not be a path.
  112.  
  113.       checkProduct -- a flag indicating whether product directories
  114.         should be used as additional hope ares to be searched. This
  115.         defaults to a true value.
  116.  
  117.         If this is true and the name contains a dot, then the
  118.         text before the dot is treated as a product name and
  119.         the product package directory is used as anothe rhome.
  120.  
  121.       suffixes -- a sequences of file suffixes to check.
  122.         By default, the name is used without a suffix.
  123.  
  124.     The search takes on multiple homes which are INSTANCE_HOME,
  125.     the directory containing the directory containing SOFTWARE_HOME, and
  126.     possibly product areas.     
  127.     """
  128.     d,n = path_split(name)
  129.     if d: raise ValueError, (
  130.         'The file name, %s, should be a simple file name' % name)
  131.  
  132.     if checkProduct:
  133.        l = find(name, '.')
  134.        if l > 0:
  135.            p = name[:l]
  136.            n = name[l + 1:]
  137.            for product_dir in Products.__path__:
  138.                r = _getPath(product_dir, '%s/%s/' % (p, prefix), n, suffixes)
  139.                if r is not None: return r
  140.  
  141.     sw=path_split(path_split(SOFTWARE_HOME)[0])[0]
  142.     for home in (INSTANCE_HOME, sw):
  143.         r=_getPath(home, prefix, name, suffixes)
  144.         if r is not None: return r
  145.  
  146. def getObject(module, name, reload=0,
  147.               # The use of a mutable default is intentional here,
  148.               # because modules is a module cache.
  149.               modules={} 
  150.               ):
  151.  
  152.     # The use of modules here is not thread safe, however, there is
  153.     # no real harm in a rece condition here.  If two threads
  154.     # update the cache, then one will have simply worked a little
  155.     # harder than need be.  So, in this case, we won't incur
  156.     # the expense of a lock.
  157.     if modules.has_key(module):
  158.         old=modules[module]
  159.         if old.has_key(name) and not reload: return old[name]
  160.     else:
  161.         old=None
  162.  
  163.     if module[-3:]=='.py': p=module[:-3]
  164.     elif module[-4:]=='.pyp': p=module[:-4]
  165.     elif module[-4:]=='.pyc': p=module[:-4]
  166.     else: p=module
  167.     p=getPath('Extensions', p, suffixes=('','py','pyp','pyc'))
  168.     if p is None:
  169.         raise "Module Error", (
  170.             "The specified module, <em>%s</em>, couldn't be found." % module)
  171.  
  172.     __traceback_info__=p, module
  173.  
  174.  
  175.     if p[-4:]=='.pyc':
  176.         file = open(p, 'rb')
  177.         binmod=imp.load_compiled('Extension', p, file)
  178.         file.close()
  179.         m=binmod.__dict__
  180.  
  181.     elif p[-4:]=='.pyp':
  182.         prod_id=split(module, '.')[0]
  183.         data=zlib.decompress(
  184.             rotor.newrotor(prod_id +' shshsh').decrypt(open(p,'rb').read())
  185.             )
  186.         execsrc=compile(data, module, 'exec')
  187.         m={}
  188.         exec execsrc in m
  189.         
  190.     else:
  191.         try: execsrc=open(p)
  192.         except: raise "Module Error", (
  193.             "The specified module, <em>%s</em>, couldn't be opened."
  194.             % module)
  195.         m={}
  196.         exec execsrc in m
  197.  
  198.     try: r=m[name]
  199.     except KeyError:
  200.         raise 'Invalid Object Name', (
  201.             "The specified object, <em>%s</em>, was not found in module, "
  202.             "<em>%s</em>." % (name, module))
  203.  
  204.     if old:
  205.         for k, v in m.items(): old[k]=v
  206.     else: modules[module]=m
  207.  
  208.     return r
  209.  
  210. class NoBrains: pass
  211.  
  212. def getBrain(module, class_name, reload=0):
  213.     'Check/load a class'
  214.  
  215.     if not module and not class_name: return NoBrains
  216.  
  217.     try: c=getObject(module, class_name, reload)
  218.     except KeyError, v:
  219.         if v == class_name: raise ValueError, (
  220.             'The class, %s, is not defined in file, %s' % (class_name, module))
  221.  
  222.     if not hasattr(c,'__bases__'): raise ValueError, (
  223.         '%s, is not a class' % class_name)
  224.     
  225.     return c
  226.